﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using SimpleJson;
using System;
using Pomelo.DotNetClient;
using System.Threading;
using System.Collections;



public class niuniu : MonoBehaviour
{

    // Use this for initialization
    public static niuniu last = null;
    public PomeloClient pc;
    public string roomid;
    //用于 握手的key  
    public static string HandShakeKey = "agashgw123pajloaxn34ga8xrunpagkjwlaw456xnpaagl29w4rxn";
    public int waitePlay = 0;
    public bool shouldRemove = false;
    public niuniu[] otherPlayer = null;
    // Use this for initialization
    void Start()
    {
        last = this;
    }
    /// <summary>
    /// 创建三个机器人加入  roomid 
    /// </summary>
    /// <param name="rid">roomid</param>
    public void CreateOther(string rid)
    {
        //return;
        otherPlayer = new niuniu[3];
        for (var i = 0; i < 3; i++)
        {
            niuniu others = gameObject.AddComponent<niuniu>();
            others.login(rid);
            otherPlayer[i] = others;
        }
        Invoke("StartTheGame", 2);

    }

    public void StartTheGame()
    {
        JsonObject arg = new JsonObject();
        CallRemote("connector.roomHandler.StartGame", arg, (gms)=> { });
    }
    public static string host = "127.0.0.1";
    public static int port = 7821;
    public static int gWanfa = 0;
    public static int gHufa = 0;
    public static int GameType = 1;
    /// <summary>
    /// 创建一个房间 然后加入三个机器人
    /// </summary>
    /// <param name="rid">roomid</param>

    public void CreateGame()
    {
        pc = new PomeloClient();
        Debug.Log(host);
        pc.initClient(host, port);
        JsonObject shakemsg = new JsonObject();
        shakemsg["key"] = HandShakeKey;
        if (StartIndex < 0)
            StartIndex = (int)(UnityEngine.Random.value * 1000) + 9000;
        string str = "" + StartIndex++;
        //0.握手的时候 带上 这个key， 不带的话我这边就会跑去链接
        pc.connect(shakemsg, (data) =>
        {
            Debug.Log("connection compelete" + data);
            GlobeCount.Instance.AddCount(GameStatus.ConnectPlatformSucess);
            JsonObject msg = new JsonObject();
            //msg["openid"] = str;
            //msg["access_token"] = "robot_immunity";
            print(str);
            msg["key"] = str;
            msg["type"] = 2;
            CallRemote("platform.platformHandler.HHAuthor", msg, OnQuery);
        });
        //}, System.Threading.ThreadPriority.Normal, true);
    }

    void Reconnect()
    {
        pc.disconnect();

        pc = new PomeloClient();
        pc.initClient(gHost, gPort);
        JsonObject shakemsg = new JsonObject();
        shakemsg["key"] = HandShakeKey;
        string str = "robot_" + StartIndex++;
        //0.握手的时候 带上 这个key， 不带的话我这边就会跑去链接
        pc.connect(shakemsg, (data) =>
        {
            Debug.Log("connection compelete" + data);
            JsonObject msg = new JsonObject();
            msg["uid"] = uid;
            msg["token"] = gToken;
            CallRemote("connector.hhuserHandler.Login", msg, OnLogin);
        });
    }

    public static int StartIndex = -1;
    public void login(string rid)
    {
        //Loom.StartSingleThread(()=>{
        roomid = rid;
        //string host = "127.0.0.1";
        //int port = 4008;
        //string host = "120.76.182.17";
        //int port = 7821;
        pc = new PomeloClient();
        pc.initClient(host, port);
        JsonObject shakemsg = new JsonObject();
        shakemsg["key"] = HandShakeKey;
        if (StartIndex < 0)
            StartIndex = (int)(UnityEngine.Random.value * 1000) + 9000;
        string str = "" + StartIndex++;
        //0.握手的时候 带上 这个key， 不带的话我这边就会跑去链接
        pc.connect(shakemsg, (data) =>
        {
            Debug.Log("connection compelete" + data);
            JsonObject msg = new JsonObject();
            //msg["openid"] = str;
            //msg["access_token"] = "robot_immunity";
            msg["key"] = str;
            Debug.Log(str);
            msg["type"] = 2;
            GlobeCount.Instance.AddCount(GameStatus.ConnectPlatformSucess);
            CallRemote("platform.platformHandler.HHAuthor", msg, OnQuery);
        });

        //  }, System.Threading.ThreadPriority.Normal, true);
    }
    public string uid;
    public int idx = -1;
    public string gHost;
    public int gPort;
    public string gToken;
    void OnQuery(JsonObject result)
    {
        Debug.Log(result);
        if (Convert.ToInt32(result["code"]) == 0)
        {
            pc.disconnect();
            //shouldRemove = true;
            //return;
            GlobeCount.Instance.AddCount(GameStatus.AuthSucced);
            string host = (string)result["host"];
            int port = Convert.ToInt32(result["port"]);
            pc = new PomeloClient();
            pc.initClient(host, port);
            gHost = host;
            gPort = port;
            pc.NetWorkStateChangedEvent += (state) =>
            {
                if (state == NetWorkState.DISCONNECTED)
                {
                    Debug.LogError(uid + ":" + idx + " lose !");
                    GlobeCount.Instance.AddCount(GameStatus.Disconnect);
                    GlobeCount.Instance.dead++;
                    // gameObject.SetActive(false);
                }
            };

            JsonObject shakemsg = new JsonObject();
            shakemsg["key"] = HandShakeKey;
            uid = result["uid"].ToString();
            //同样带上key
            pc.connect(shakemsg, (data) =>
            {
                GlobeCount.Instance.AddCount(GameStatus.ConnectorSucess);
                Debug.Log("connection compelete" + data);
                JsonObject msg = new JsonObject();
                msg["uid"] = result["uid"];
                msg["token"] = result["token"];
                gToken = result["token"] as string;
                //2. connector登入操作 返回用户信息
                //{"name":"3D Coffice","sex":1,"head":"http://wx.qlogo.cn/mmopen/PiajxSqBRaEIrZyEsQIv1C5Uxiac0wicaICWticoLSCc4IVTIg4gegs5a4TicI79Zk35CrqVXILIkFibDwjRHcPjn9hQ/0","ip":"127.0.0.1","cardNum":8}
                CallRemote("connector.hhuserHandler.Login", msg, OnLogin);

            });
            pc.on("closing", (jdata) =>
            {
                Debug.Log("closed" + jdata);
            });
            pc.on("disconnect", (jdata) =>
            {
                Debug.Log("disconnect" + jdata);
            });
        }
    }
    bool canCreate = false;

    void GetIdx(JsonObject obj)
    {
        JsonObject users = obj["users"] as JsonObject;

        for (var i = 0; i < 4; i++)
            if ((users[i] as JsonObject)["uid"].ToString() == uid)
            {
                idx = i;
                return;
            }
    }
    public JsonArray selfCard = null;
    public int gui = -1;
    public bool hasAdd = false;
    int ToInt(object obj)
    {
        return System.Convert.ToInt32(obj);
    }
    void OnLogin(JsonObject result)
    {
        Debug.Log("login return:" + result);
        JsonObject arg = new JsonObject();
        GlobeCount.Instance.AddCount(GameStatus.Login);
        //CallRemote("connector.userHandler.getUserRecords", arg, (ret) =>
        //{
        //    Debug.Log("getUserRecords" + ret);
        //});
        if (string.IsNullOrEmpty(roomid))
        {
            JsonObject msg = new JsonObject();
            msg["cost"] = 1;
            msg["opt"] = new JsonObject();
            msg["gtype"] = 2;
            JsonObject opt = msg["opt"] as JsonObject;
            opt["in"] = 1;
            opt["type"] = 4; 
            opt["wanfa"] = 1|2|4|8|16; 
            opt["hufa"] = 2 + 250*256;
            opt["gtype"] = 2;
            CallRemote("connector.roomHandler.createGroupRoom", msg, (ret) =>
            {
                GlobeCount.Instance.AddCount(GameStatus.InRoom);

            });
        }
        else
        {
            arg["rid"] = roomid;
            CallRemote("connector.roomHandler.joinRoom", arg, (ret) =>
            {
                GlobeCount.Instance.AddCount(GameStatus.InRoom);


            });
        }
        var gobj = new JsonObject();
        gobj["state"] = 1;
        gobj["x"] = 110.021f;
        gobj["y"] = -12.0f;
        CallRemote("connector.userHandler.updateGPS", gobj, (sret) =>
        {
            Debug.Log("updateGPS:" + sret);
        });
        pc.on("OnGPS", (gmsg) =>
        {
            Debug.Log("OnGPS:" + gmsg);
        });

        pc.on("OnRoomInfo", (ret) =>
        {
           
            roomid = ret["id"].ToString();
            GetIdx(ret);
            Debug.Log(idx + "OnRoomInfo:" + ret);
            if (idx == 0 && hasAdd == false)
            {
                hasAdd = true;
                canCreate = true;
            }
            else if (idx == 0 && hasAdd)
            {
                for (var i = 0; i < otherPlayer.Length; i++)
                {
                    otherPlayer[i].Rejoinroom(roomid);
                }
            }
        });
        pc.on("OnNet", (gmsg) =>
        {
            Debug.Log("OnNet:" + gmsg);
        });
        pc.on("OnAdd", (gmsg) =>
        {
            Debug.Log(idx+"OnAdd:" + gmsg);
        });

        pc.on("OnLeave", (gmsg) =>
        {
            Debug.Log("OnLeave:" + gmsg);
        });
        pc.on("shushu", (gmsg) =>
        {
            Debug.Log("shushu:" + gmsg);
        });
        pc.on("OnClose", (gmsg) =>
        {
            Debug.Log("OnClose:" + gmsg);
        });
        pc.on("OnReady", (gmsg) =>
        {
            Debug.Log("OnReady:" + gmsg);
        });
        pc.on("OnRoomClose", (gmsg) =>
        {
            GlobeCount.Instance.AddCount(GameStatus.GameOver);
            roomid = "";
            Debug.Log("OnRoomClose:" + gmsg);
            pc.request("connector.userHandler.getUserRecords", arg, (ret) =>
            {
                Debug.Log("getUserRecords" + ret);
            });
        });
        pc.on("OnChoose", (gmsg) =>
        {
            Debug.Log("OnChoose:" + gmsg);
            var agreeMsg = new JsonObject();
            agreeMsg["sel"] = 2;
            CallRemote("niuniu.roomHandler.agreeClose", agreeMsg, (rret) => {
            });
            //CallRemote
        });
        pc.on("OnStart", (gmsg) =>
        {
            GlobeCount.Instance.AddCount(GameStatus.GameStart);
            Debug.Log(idx + "Start:" + gmsg);
            gui = ToInt(gmsg["gui"]);
            selfCard = ((gmsg["players"] as List<object>)[idx] as JsonObject)["card"] as JsonArray;
            Debug.Log(idx + "Start:" + selfCard);
        });
        pc.on("OnNiuStart", (gmsg) =>
        {
            GlobeCount.Instance.AddCount(GameStatus.GameStart);
            Debug.Log(idx + "Start:" + gmsg);
            //gui = ToInt(gmsg["gui"]);
            //selfCard = ((gmsg["players"] as List<object>)[idx] as JsonObject)["card"] as JsonArray;
            //Debug.Log(idx + "Start:" + selfCard);
        });
        pc.on("OnSetZhuang", (gmsg) =>
        {
            Debug.Log(idx + "OnSetZhuang:" + gmsg);
        });
        pc.on("OnNiuCall", (gmsg) =>
        {
            Debug.Log(idx+"OnNiuCall:" + gmsg);
            //return;
            lastCall = gmsg;
            waitePlay = 90;
            return;
        });
        pc.on("OnCardUpdate", (gmsg) =>
        {
            Debug.Log("OnCardUpdate:" + gmsg);
        });
        /*
         op val 就是上面操作的通知，通知所有玩家
         */
        pc.on("OnNiuPlay", (gmsg) =>
        {
            DateTime now = System.DateTime.Now;
            //now = (now - begin).Ticks; 
            //float compelete = Time.time;
            Debug.Log(idx.ToString() + " OnNiuPlay " + gmsg);
            //if (idx.ToString().CompareTo(gmsg["idx"].ToString()) == 0)
            //{
            //    GlobeCount.Instance.CountQPS("OnPlay", (now - OnCallbegin).TotalMilliseconds);
            //    Debug.Log("OnPlay:" + gmsg);
            //}
        });
        /*
         {"ma":[0,16,13,22,30,0],"players":[{"card":[0,0,0,1,1,1,2,2,2,3,3,3,4,4],"his":[],"heap":[],"score":1006},{"card":[33,1,4,6,8,10,13,17,18,19,20,22,23],"his":[],"heap":[],"score":998},{"card":[33,3,9,9,10,14,19,22,24,26,26,27,29],"his":[],"heap":[],"score":998},{"card":[2,3,4,9,14,18,21,21,23,23,25,27,29],"his":[],"heap":[],"score":998}],"hu":{"0":{"mutil":2,"way":1,"cards":[0,0,0,1,1,1,2,2,2,3,3,3,4,4],"guiIdx":[],"zhong":[0,2,3,5]}}}
         游戏结算的通知
         *   ma  开的六章马牌
         *   players 玩家的游戏数据
         *   hu  胡的信息，里面可能有多个玩家一起胡
         *      mutil 倍率
         *      way  胡法   1<<n 位运算的方式表示
         *      cards 胡牌的队列 
         *      guiIdx 数组 表示上面card里面的idx是鬼变的 类似的cards[0, 1, 1, 1, 0], guiidx [2, 3] 里面的 2 、3位置的1是鬼变的
         *      zhong  中码，自己中码的信息 如[0,2,3,5],就是中了ma[0] ma[2] ma[3] ma[5]
         */

        pc.on("OnNiuEnd", (gmsg) =>
        {

            //JsonObject arg = new JsonObject();
            //if(idx == 1)
            //pc.request("niuniu.roomHandler.leaveRoom", arg, (sret) =>
            //{
            //    Debug.Log("Leavel" + sret);
            //});
            //return;
            Debug.Log(idx + "end:" + gmsg);
            //return;
            //if (idx == 0)
            //    return;
            var msg = new JsonObject();
            //pc.request("game.roomHandler.getRoomInfo", msg, (sret) =>
            //{
            //    Debug.Log("getRoomInfo" + sret);
            //});
            //CallRemote("niuniu.gameHandler.getGameUpdate", msg, (nmsg) =>
            //{
            //    Debug.Log("getGameUpdate" + nmsg);
            //});
            //msg["ready"] = 1;
            //CallRemote("niuniu.roomHandler.ready", msg, (obj) => { });
        });
    }

    public void RecreateRoom()
    {
        JsonObject msg = new JsonObject();
        msg["cost"] = 1;
        msg["opt"] = new JsonObject();
        JsonObject opt = msg["opt"] as JsonObject;
        opt["type"] = 2; //1 鸡胡 2 100张
        opt["ma"] = 0; // 0 2 4 6
        opt["gui"] = 2; // 0 无鬼 1白板做鬼 
        //opt["wanfa"] = WanFa.meiwan | WanFa.genpai | WanFa.qianggang | WanFa.qianggangquanbao | WanFa.gangbaoquanbao | WanFa.zanpaiquanbao | WanFa.yijiuwan | WanFa.qghfanbei; //跟牌 0 1
        //opt["hufa"] = HuFa.shisan | HuFa.quanbao | HuFa.quanfeng | HuFa.quanyao | HuFa.qingyise;
        opt["wanfa"] = WanFa.genpai | WanFa.gangkaijiabei;
        opt["hufa"] = HuFa.qidui | HuFa.haohuaqidui | HuFa.dadiaoche | HuFa.jiada | HuFa.haidi;
        //JsonObject opt = msg["opt"] as JsonObject;
        //opt["ma"] = 6; // 0 2 4 6
        //opt["gui"] = 1; // 0 无鬼 1白板做鬼  2选鬼
        //opt["qidui"] = 1; //0不可以胡  1可胡七对  2七对加倍
        //opt["qiang"] = 1; //0不可抢   1可抢  2明杠可抢
        //opt["qupai"] = 1 << 4; //位运算  0不去除  1 2 3 4  万 饼 锁 字    1<<4 | 1<<3 去锁 指
        //opt["quanbao"] = 1 << 1 | 1 << 2; //位运算  0不全包   1<<1 抢杠全包  1<<2杠爆全包   
        //opt["laoyue"] = 1;//海底捞月 0 1
        //opt["genpai"] = 1;//庄家派利是 跟牌  0 1

        CallRemote("connector.userHandler.createRoom", msg, (ret) =>
        {
            GlobeCount.Instance.AddCount(GameStatus.InRoom);
            Debug.Log("createRoom:" + ret);
            roomid = ret["id"].ToString();
            // GetIdx(ret);

        });
    }
    public void Rejoinroom(string rid)
    {
        roomid = rid;
        JsonObject arg = new JsonObject();
        arg["rid"] = rid;
        CallRemote("connector.userHandler.joinRoom", arg, (ret) =>
        {
            GlobeCount.Instance.AddCount(GameStatus.InRoom);
            // Debug.Log(uid + "joinRoom:" + ret);
            //GetIdx(ret);

        });
    }
    float NoneRate = 0.0f;
    private void OnCall(JsonObject gmsg)
    {
        int op = ToInt(gmsg["op"]);
        //int val = ToInt(gmsg["val"]);
        //Debug.Log(op + "  " + val);
        var msg = new JsonObject();

        OnCallbegin = System.DateTime.Now;
        if ((op & NiuOperationResult.Bet) != 0)
        {
            msg["op"] = NiuOperationResult.Bet;
            JsonArray arr = gmsg["val"] as JsonArray;
            msg["val"] = arr[(int)(UnityEngine.Random.value*arr.Count)];

            //msg["val"] = 0;
            Debug.Log(idx + "Bet card " + msg);
            CallRemote("niuniu.gameHandler.operation", msg, (obj) => { });
        }
        else if ((op & NiuOperationResult.Qiang) != 0)
        {
            msg["op"] = NiuOperationResult.Qiang;

            JsonArray arr = gmsg["val"] as JsonArray;
            msg["val"] = arr[(int)(UnityEngine.Random.value * arr.Count)];

            //msg["val"] = 0;
            Debug.LogWarning(idx + "qiang card " + msg);
            CallRemote("niuniu.gameHandler.operation", msg, (obj) => { });
        }
        else if ((op & NiuOperationResult.Show) != 0)
        {
            msg["op"] = NiuOperationResult.Show;
      
            msg["val"] = 0;

            //msg["val"] = 0;
            Debug.LogWarning(idx + "show card " + msg);
            CallRemote("niuniu.gameHandler.operation", msg, (obj) => { });
        }
    }

    public void RemoveCard(int val, int num)
    {
        Debug.Log(val + "  " + num + "  " + selfCard);
        for (var i = selfCard.Count - 1; 0 <= i && num > 0; i--)
        {
            var cur = ToInt(selfCard[i]);
            if (cur == val)
            {
                selfCard.RemoveAt(i);
                num--;
            }

        }
        Debug.Log(val + " after " + num + "  " + selfCard);
    }
    public int RemoveChiCard(int val)
    {
        Debug.LogWarning(val + " chi " + selfCard);

        int cur = (int)Math.Floor(val / 9f);
        for (int i = -2; i < 1; i++)
        {
            bool find = true;
            for (int j = 0; j < 3 && find; j++)
                if (i + j != 0)
                {
                    int v = val + i + j;
                    if (((int)Math.Floor(v / 9f)) != cur)
                    {
                        find = false;
                        break;
                    }
                    var findCard = false;
                    for (var ii = selfCard.Count - 1; 0 <= ii; ii--)
                    {
                        if (ToInt(selfCard[ii]) == v)
                        {
                            findCard = true;
                            break;
                        }
                    }
                    if (findCard == false)
                        find = false;
                }
            if (find == true)
            {
                for (int j = 0; j < 3 && find; j++)
                    if (i + j != 0)
                    {
                        int v = val + i + j;
                        for (var ii = selfCard.Count - 1; 0 <= ii; ii--)
                        {
                            if (ToInt(selfCard[ii]) == v)
                            {
                                selfCard.RemoveAt(ii);
                                break;
                            }
                        }
                    }
                Debug.Log(val + " chiafter " + selfCard);
                return i + val;
            }
        }

        return -1;
    }
    public int AI_go()
    {
        Dictionary<int, int> counter = new Dictionary<int, int>();
        int ret = 0;
        for (var i = 0; i < selfCard.Count; i++)
        {
            var cur = ToInt(selfCard[i]);
            if (counter.ContainsKey(cur))
            {
                counter[cur]++;
                continue;
            }
            counter.Add(cur, 1);
        }
        for (int i = 33; 0 < i; i--)
        {
            if (i == gui)
                continue;
            if ((counter.ContainsKey(i) && counter[i] > 0) && (i < 9 || (10 < i && i < 18) || (19 < i && i < 27)))
            {
                int j = i + 1, k = i + 2;
                if ((counter.ContainsKey(j) && counter[j] > 0) && (counter.ContainsKey(k) && counter[k] > 0))
                {
                    counter[i]--;
                    counter[j]--;
                    counter[k]--;
                    i++;
                    continue;
                }

            }
            if (counter.ContainsKey(i) && counter[i] >= 2)
            {
                continue;
            }
            if (counter.ContainsKey(i) && counter[i] == 1)
                return i;
        }

        int sel = (int)Math.Floor(UnityEngine.Random.value * selfCard.Count);
        return ToInt(selfCard[sel]);
    }
    public JsonObject lastCall = null;
    public DateTime OnCallbegin = System.DateTime.Now;
    public void CallRemote(string route, JsonObject msg, Action<JsonObject> cb)
    {
        countDeth = 0;
        DateTime begin = System.DateTime.Now;
        //float begin = System.DateTime.Now.get;
        pc.request(route, msg, (obj) =>
        {
            DateTime now = System.DateTime.Now;
            //now = (now - begin).Ticks; 
            //float compelete = Time.time;
            GlobeCount.Instance.CountQPS(route, (now - begin).TotalMilliseconds);
            Debug.Log(idx + " t " + (now - begin).TotalMilliseconds + " : " + route + obj);
            if (obj.ContainsKey("code") && ToInt(obj["code"]) > 0)
            {
                Debug.LogError(uid + " " + msg + " : " + route + obj);
                // CallRemote(route, msg, cb);
            }
            else
            {
                cb(obj);
            }

        });


    }
    public int countDeth = 0;
    void CallLast()
    {
        OnCall(lastCall);
        lastCall = null;
    }
    void Update()
    {
        countDeth++;
        if (countDeth > 3000)
        {
            //GlobeCount.Instance.dead++;
            //gameObject.SetActive(false);
        }
        if (shouldRemove)
            Destroy(this.gameObject);
        if (canCreate && !string.IsNullOrEmpty(roomid))
        {

            CreateOther(roomid);
            //Invoke("Reconnect", 1);
            canCreate = false;
        }
        if (waitePlay > 0 && lastCall != null)
        {
            waitePlay = 0;
            Invoke("CallLast", 0.33f);
        }


        if (string.IsNullOrEmpty(roomid) && otherPlayer != null && otherPlayer.Length == 3)
        {
            roomid = "1";
            //Invoke("RecreateRoom", 3);
            //RecreateRoom();
        }
    }
}
